import {EventEmitter} from "../../node-test";
import log from '../logger'
import readyState from "./0ready";
import {State, StateInterface} from "../interfaces";
import plate from "../plate";
import controller from "../controller";
import weighter from "../weight";
import settings from "../settings";
import player from "../player";
import container from "../container";
import qr from "../qr";
import {readFileSync, writeFile} from "fs";
import weightState from "./2weight";
import mqttIot from "../mqttiot";

class StateImpl extends EventEmitter implements State {
    private _stateContext: StateInterface;

    enable = true;
    public inout: 'in' | 'out' = 'in'
    vehicleNumber: Map<string, number> = new Map()
    public wenWeight = 0
    // 用来准备上传重量变化
    public weighRecordId = 0
    public container1 = '';
    public container2 = '';
    public isPurchase = false;
    public isSale = false;
    public isSecond = false;
    // 关闭销售按钮过磅
    public closeSaleBtnWeighing = false;
    // 是否倒车，如果倒车，下磅时候不再进行关闸动作；
    public isBack = false;
    public warehouse = "";
    public location = "";
    public senderName = "";
    public customerName = "";
    // 集装箱过磅相关业务
    // 矿发重量
    public primaryWeight = 0;
    // 期望集装箱实收净重（集装箱业务）
    public expectedNetWeight = 0;
    // 是否人工过磅
    public manualDoWeigh = false;

    backVehicle = {
        carNum: "",
        time: new Date().getTime()
    }

    clearState() {
        log.info("清除本地持久化状态")
        writeFile('state.json', "", 'utf-8', (err: any) => {
            if (err) {
                log.error('writeFile error: ', err);
            } else {
                log.info("写入本地持久化状态")
            }
        });
    }

    writeState() {
        const d = {
            inout: this.inout,
            vehicleNumber: this.getVehicleNumber(),
            container1: this.container1,
            container2: this.container2,
            isSale: this.isSale,
            isSecond: this.isSecond,
            isBack: this.isBack,
            warehouse: this.warehouse,
            location: this.location,
            senderName: this.senderName,
            customerName: this.customerName
        }
        writeFile('state.json', JSON.stringify(d, null, 4), 'utf-8', (err: any) => {
            if (err) {
                log.error('writeFile error: ', err);
            } else {
                log.info("写入本地持久化状态")
            }
        });
    }

    readState() {
        try {
            const data = readFileSync('state.json');
            if (data !== null && data !== undefined && data.toString() !== "") {
                const d = JSON.parse(data.toString());
                log.info("读取本地持久化状态:", d);
                this.stateContext = weightState;
                this.addPlate(d.vehicleNumber, d.inout, 100);
                this.container1 = d.container1;
                this.container2 = d.container2;
                this.isSale = d.isSale;
                this.isSecond = d.isSecond;
                this.isBack = d.isBack;
                this.warehouse = d.warehouse;
                this.location = d.location;
                this.senderName = d.senderName;
                this.customerName = d.customerName;
            } else {
                log.info("本地持久化状态为空");
                this.stateContext = readyState;
            }
        } catch (e) {
            this.stateContext = readyState;
            log.warn("没有state.json文件")
        }
    }

    get stateContext() {
        return this._stateContext
    }

    set stateContext(state: StateInterface) {
        if (this._stateContext) {
            log.info('state from ' + this._stateContext.name + ' to ' + state.name);
            this._stateContext.leave()
        }
        this._stateContext = state
        state.init()
        this.emit('state', this.stateContext.name)
    }

    public constructor() {
        super();
    }

    driverRequest(type: string): void {
        this.stateContext.driverRequest(type);
    }

    init() {
        // this.stateContext = readyState;
        // 读取持久化状态
        this.readState();
        container.on('container', (value: string) => {
            this.container1 = value;
        })
        plate.on('plate', (vehicleNumber: string, inout: 'in' | 'out') => {
            if (this.enable) {
                log.info('emit plate', vehicleNumber, inout);
                this.stateContext.plate(vehicleNumber, inout);
            } else {
                player.say("设备禁用，禁止过磅");
            }
        })
        qr.on('qr', (vehicleNumber: string, inout: 'in' | 'out') => {
            if (this.enable) {
                log.info('emit qr', vehicleNumber, inout);
                this.addPlate(vehicleNumber, inout, 100);
                this.stateContext.plate(vehicleNumber, inout);
            } else {
                player.say("设备禁用，禁止过磅");
            }
        })
        controller.on('active', (R: boolean[]) => {
            log.info('emit active', R)
            this.stateContext.active(R)
        })
        weighter.on("weight_data", (weight: number, wen: boolean) => {
            log.info('emit weight_data', weight, 'wen:', wen)
            this.stateContext.weight_data(weight, wen)
        });
        mqttIot.on("do_weigh", (data: any) => {
            this.stateContext.do_weigh(data.weight, data.deductionWeight);
        })
    }

    addPlate(vehicleNumber: string, inout: "in" | "out", times = 1): boolean {
        this.inout = inout
        const count = this.vehicleNumber.get(vehicleNumber) || 0;
        this.vehicleNumber.set(vehicleNumber, count + times)
        return count + times > settings.readyPlateNum;
    }

    hasVehicleNumber(): boolean {
        return this.vehicleNumber.size > 0
    }

    getVehicleNumber(): string {
        let max = 0
        let maxVehicleNumber = ""
        this.vehicleNumber.forEach((value, key) => {
            if (value > max) {
                max = value
                maxVehicleNumber = key
            }
        })
        return maxVehicleNumber
    }

    clear() {
        log.info('data clear')
        // if (data.isUpdate === false) {
        // 上传未识别车牌或者识别车牌没有稳定的记录 todo
        // }
        // this.isUpdate = false
        this.vehicleNumber = new Map()
        this.wenWeight = 0
        this.weighRecordId = 0
        this.container1 = ''
        this.container2 = ''
        this.isSale = false
        this.isSecond = false
        this.closeSaleBtnWeighing = false
        this.isBack = false
        this.warehouse = ""
        this.location = ""
        this.senderName = ""
        this.customerName = ""
        this.primaryWeight = 0
        this.expectedNetWeight = 0
        this.manualDoWeigh = false
    }
}

const state = new StateImpl();
export default state;